package top.glkj.hms.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.glkj.hms.dao.RoomDao;
import top.glkj.hms.dao.RoomTypeDao;
import top.glkj.hms.dao.UserDao;
import top.glkj.hms.dao.UserDetailDao;
import top.glkj.hms.entity.Room;
import top.glkj.hms.entity.RoomType;
import top.glkj.hms.entity.User;
import top.glkj.hms.entity.UserDetail;
import top.glkj.hms.exception.DefineException;
import top.glkj.hms.service.RoomService;
import top.glkj.hms.utils.*;

import javax.persistence.criteria.*;
import java.util.*;

/**
 * @author : xgl
 * @version : 0.0.1
 * @date :2020/12/7 23:38
 */
@Service
@Slf4j
public class RoomServiceImpl implements RoomService {
    private final RoomDao roomDao;
    private final RoomTypeDao roomTypeDao;
    private final UserDao userDao;
    private final UserDetailDao userDetailDao;
    @Autowired
    public RoomServiceImpl(RoomDao roomDao, UserDao userDao, RoomTypeDao roomTypeDao, UserDetailDao userDetailDao) {
        this.roomDao = roomDao;
        this.userDao = userDao;
        this.roomTypeDao = roomTypeDao;
        this.userDetailDao = userDetailDao;
    }

    /**
     * 获取所有用户，按分页方式
     *
     * @return List<T>
     */
    @Override
    public Result getAll() {
        List<Room> all = roomDao.findAll();
        if (all.isEmpty()){
            return ResultFactory.isNotFound(StaticValue.DATA_NOT_FOUND);
        }
        return ResultFactory.isSuccess(StaticValue.GET_DATA_SUCCESS,all);
    }

    /**
     * 获取所有用户，按分页方式
     *
     * @param id id
     * @return T t
     */
    @Override
    public Result getOne(Long id) {
        Optional<Room> byId = roomDao.findById(id);
        Room room = byId.orElse(null);
        if (room==StaticValue.NULL){
            return ResultFactory.isError(StaticValue.DATA_NOT_FOUND);
        }else{
            return ResultFactory.isSuccess(StaticValue.GET_DATA_SUCCESS,room);
        }
    }

    /**
     * 修改或者保存
     *
     * @param room T t
     * @return true or false
     */
    @Override
    public Result save(Room room) {
        try {
            Room save = roomDao.save(room);
            return ResultFactory.isSuccess(StaticValue.SUCCESS_MESSAGE,save);
        }catch (Exception e){
            log.error(e.getMessage());
            return ResultFactory.isError(StaticValue.ERROR_MESSAGE);
        }
    }

    /**
     * 彻底从数据库中删除实体{T}
     *
     * @param room T t
     * @return true or false
     */
    @Override
    public Result delete(Room room) {
        try {
            roomDao.delete(room);
            return ResultFactory.isSuccess(StaticValue.DELETE_DATA_SUCCESS);
        }catch (Exception e){
            log.error(e.getMessage());
            return ResultFactory.isError(StaticValue.DELETE_DATA_ERROR,e);
        }
    }

    /**
     * 标记删除
     *
     * @param room T t
     * @return true or false
     */
    @Override
    public Result remove(Room room) {
        room.setStatus(Status.Delete);
        room.setDel(true);
        room.setUpdateTime(new Date());

        return save(room);
    }

    @Override
    public Result addRoom(Room room) {
        room.setCreateTime(new Date());
        room.setUpdateTime(new Date());
        room.setDel(false);
        room.setCreateUserId(getCurrentUser().getId());
        room.setUpdateUserId(getCurrentUser().getId());
        return save(room);
    }

    @Override
    public Result updateRoom(Room room) {
        room.setUpdateTime(new Date());
        room.setUpdateUserId(getCurrentUser().getId());
        return save(room);
    }

    @Override
    public Result getRoomByPageAndSize(int page, int size) {
        GlUtils<Room,RoomDao> glUtils = new GlUtils<>();

        return glUtils.getAllByPageAndSize(page,size,roomDao);
    }

    @Override
    public Result getRoomByPageAndSizeAndSearch(int page, int size, Map<String, String> searchValue) {
        GlUtils<Room,RoomDao> glUtils = new GlUtils<>();
        return glUtils.getAllByPageAndSizeAndAnyArgs(page,size,searchValue,roomDao);
    }

    @Transactional(rollbackFor = DefineException.class)
    @Override
    public Result addAllRoom(List<Room> roomList) throws DefineException {
        try {
            List<Room> rooms = roomDao.saveAll(roomList);
            if (rooms.size()!=roomList.size()) {
                throw new DefineException(StaticValue.ADD_DATA_ERROR);
            }
            return ResultFactory.isSuccess(StaticValue.ADD_DATA_SUCCESS,rooms);
        }catch (Exception e){
            throw new DefineException(StaticValue.ADD_DATA_ERROR);
        }
    }

    @Override
    public Result getRoomByStatus(Status status) {
        List<Room> all = roomDao.findAllByStatus(status);
        if (all.isEmpty()){
            return ResultFactory.isNotFound(StaticValue.DATA_NOT_FOUND);
        }
        return ResultFactory.isSuccess(StaticValue.GET_DATA_SUCCESS,all);
    }

    @Override
    public Result getRoomByPrice(double minValue, double maxValue) {
        List<Room> all = roomDao.findAllByDailyRent(minValue, maxValue);
        if (all.isEmpty()){
            return ResultFactory.isNotFound(StaticValue.DATA_NOT_FOUND);
        }
        return ResultFactory.isSuccess(StaticValue.GET_DATA_SUCCESS,all);
    }

    @Override
    public Result getRoomByType(RoomType roomType) {
        List<Room> all = roomDao.findAllByRoomType(roomType);
        if (all.isEmpty()){
            return ResultFactory.isNotFound(StaticValue.DATA_NOT_FOUND);
        }
        return ResultFactory.isSuccess(StaticValue.GET_DATA_SUCCESS,all);
    }

    /**
     * 添加房间类型
     *
     * @param roomType 房间类型
     * @return 添加结果
     */
    @Override
    public Result addRoomType(RoomType roomType) {
        try {
            roomType.setCreateTime(new Date());
            roomType.setUpdateTime(new Date());
            roomType.setDel(false);
            roomType.setCreateUserId(getCurrentUser().getId());
            roomType.setUpdateUserId(getCurrentUser().getId());
            RoomType save = roomTypeDao.save(roomType);
            return ResultFactory.isSuccess(StaticValue.SUCCESS_MESSAGE,save);
        }catch (Exception e){
            log.error(e.getMessage());
            return ResultFactory.isError(StaticValue.ERROR_MESSAGE);
        }
    }

    /**
     * 删除房间类型
     *
     * @param id 编号
     * @return 删除结果
     */
    @Override
    public Result deleteRoomType(long id) {
        try {
            roomTypeDao.deleteById(id);
            return ResultFactory.isSuccess(StaticValue.DELETE_DATA_SUCCESS);
        }catch (Exception e){
            log.error(e.getMessage());
            return ResultFactory.isException(StaticValue.DELETE_DATA_ERROR,e);
        }
    }

    /**
     * 移除房间类型
     *
     * @param id 房间类型
     * @return 移除结果
     */
    @Override
    public Result removeRoomType(Long id) {
        try {
           RoomType roomType = roomTypeDao.findById(id).orElse(null);
           if (roomType==null){
               return ResultFactory.isError(StaticValue.ERROR_MESSAGE);
           }
            roomType.setUpdateTime(new Date());
            roomType.setDel(true);
            roomType.setUpdateUserId(getCurrentUser().getId());
            RoomType save = roomTypeDao.save(roomType);
            return ResultFactory.isSuccess(StaticValue.SUCCESS_MESSAGE,save);
        }catch (Exception e){
            log.error(e.getMessage());
            return ResultFactory.isError(StaticValue.ERROR_MESSAGE);
        }
    }

    /**
     * 更新房间类型
     *
     * @param roomType 房间类型
     * @return 更新结果
     */
    @Override
    public Result updateRoomType(RoomType roomType) {
        try {
            roomType.setUpdateTime(new Date());
            roomType.setUpdateUserId(getCurrentUser().getId());
            RoomType save = roomTypeDao.save(roomType);
            return ResultFactory.isSuccess(StaticValue.SUCCESS_MESSAGE,save);
        }catch (Exception e){
            log.error(e.getMessage());
            return ResultFactory.isError(StaticValue.ERROR_MESSAGE);
        }
    }

    /**
     * 分页获取房屋类型
     *
     * @param page 当前页
     * @param size 当前页
     * @return 分页获取房屋
     */
    @Override
    public Result getRoomTypeByPageAndSize(int page, int size) {
        GlUtils<RoomType,RoomTypeDao> glUtils = new GlUtils<>();
        return glUtils.getAllByPageAndSize(page,size,roomTypeDao);
    }

    /**
     * 分页和查询获取房屋类型
     *
     * @param page        当前页
     * @param size        分页大小
     * @param searchValue 查询键值对
     * @return 分页和查询获取房屋
     */
    @Override
    public Result getRoomTypeByPageAndSizeAndSearch(int page, int size, Map<String, String> searchValue) {
        GlUtils<RoomType,RoomTypeDao> glUtils = new GlUtils<>();
        return glUtils.getAllByPageAndSizeAndAnyArgs(page,size,searchValue,roomTypeDao);

    }

    /**
     * @return 查询获取房屋
     */
    @Override
    public Result getRoomType() {
        List<RoomType> all = roomTypeDao.findAll();
        return ResultFactory.isSuccess(all);
    }

    /**
     * 客人入住
     *
     * @param room 入住房间
     * @param user 入住用户
     * @return Result
     */
    @Override
    public Result intoRoom(Room room, UserDetail user) {
        User detail = userDao.getUserByUserDetail(user);
        room.setInsertUser(detail);
        room.setIntoUsers(null);
        room.setStatus(Status.CheckedIn);
        return updateRoom(room);
    }

    /**
     * 客人入住
     *
     * @param room 入住房间
     * @param user 入住用户
     * @return Result
     */
    @Override
    public Result intoBigRoom(Room room, List<UserDetail> user) {
        List<User> detail = userDao.getAllByUserDetailIn(user);
        room.setInsertUser(null);
        room.setIntoUsers(detail);
        room.setStatus(Status.CheckedIn);
        return save(room);
    }

    /**
     * 客人入住
     *
     * @param user 入住用户
     * @return Result
     */
    @Override
    public Result firstIntoBigRoom(List<UserDetail> user) {
        return null;
    }

    /**
     * 客人入住
     *
     * @param user 入住用户
     * @return Result
     */
    @Override
    public Result firstIntoRoom(UserDetail user) {
        return null;
    }

    /**
     * 根据最近时间获取客房
     *
     * @return room
     */
    @Override
    public Result getRoomByCreateTime() {
        Specification<Room> specification = (root, query, cb) -> {
            /* 1、获取比较属性 */
            Path<Object> status = root.get("status");
            return cb.equal(status, Status.Enable);
        };
        List<Room> all = roomDao.findAll(specification,Sort.by(Sort.DEFAULT_DIRECTION, "create_time"));
        if (all.isEmpty()){
            return ResultFactory.isNotFound(StaticValue.DATA_NOT_FOUND);
        }
        return ResultFactory.isSuccess(StaticValue.GET_DATA_SUCCESS,all);
    }

    @Override
    public Result getAllRoomByUserLike(User user) {
        return null;
    }

    /**
     * 根据评估获取房间
     *
     * @return room
     */
    @Override
    public Result getRoomByScore() {
        return null;
    }

    /**
     * 根据房间类型获取房间
     *
     * @return room
     */
    @Override
    public Result getRoomByType() {
        return null;
    }

    /**
     * 根据用户信息检索房间
     *
     * @param user 用户信息
     * @return 房间列表
     */
    @Override
    public Result getAllRoomByCheckUser(User user) {
        List<User> users = new ArrayList<>();
        UserDetail userDetail = userDetailDao.findFirstByIdCard(user.getUserDetail().getIdCard());
        Specification<User> spec = (root, query, cb) -> {
            /* 1、获取比较属性 */
            Path<Object> compare = root.get("phone");
            Path<Object> status = root.get("status");
            Predicate predicateStatus = cb.equal(status, Status.Enable);
            Predicate predicateCompare = cb.equal(compare, user.getPhone());
            return cb.and(predicateCompare, predicateStatus);
        };
        User one = userDao.findOne(spec).orElse(null);
        /**
         * 无用户标准信息
         */
        if (userDetail == null){
            userDetail = user.getUserDetail();
            userDetail.setDel(false);
            userDetail.setCreateTime(new Date());
            userDetail.setUpdateTime(new Date());
            userDetail.setCreateUserId(getCurrentUser().getId());
            userDetail.setUpdateUserId(getCurrentUser().getId());
        }
        /**
         * 无用户
         */
        if (one == null){
            user.setUserDetail(userDetail);
            user.setDel(false);
            user.setCreateTime(new Date());
            user.setUpdateTime(new Date());
            user.setCreateUserId(getCurrentUser().getId());
            user.setUpdateUserId(getCurrentUser().getId());
            userDao.save(user);
        }else{
            user.setDel(false);
            user.setUpdateTime(new Date());
            user.setUpdateUserId(getCurrentUser().getId());
            userDao.save(user);
        }
        /**
         * 根据用户信息检索好的房间
         */
        return getAllRoomByUserLike(user);
    }
}
